package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;

import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author xie
 * @since 2024-11-12
 */
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    @Autowired
    private  IInteractionReplyService replyService;
    @Autowired
    private  UserClient userClient;
    @Autowired
    private  SearchClient searchClient;
    @Autowired
    private  CourseClient courseClient;
    @Autowired
    private  CatalogueClient catalogueClient;
    @Autowired
    private  CategoryClient categoryClient;
    @Autowired
    private  CategoryCache categoryCache;


    /**
     * 用户端新增问题
     * @param questionFormDTO
     */
    @Override
    public void saveQustion(QuestionFormDTO questionFormDTO) {

        Long user = UserContext.getUser();

        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);

        interactionQuestion.setUserId(user);

        save(interactionQuestion);

    }

    /**
     *用户端分页查询问题
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> pageQuery(QuestionPageQuery query) {

        // 1、参数校验：课程ID和小节ID不能同时为空
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        if (ObjectUtil.isEmpty(courseId)&&ObjectUtil.isEmpty(sectionId)){
            throw new BadRequestException("课程id和小节id不能同时为空！");
        }

        // 2、分页查询问题表
        // select * from interaction_question where course_id = #{} and section_id = #{} and  user_id = #{} and hidden = 0
        // order by create_time desc limit ?,?
        Page<InteractionQuestion> description = this.lambdaQuery()
                .select(InteractionQuestion.class, column -> !column.getColumn().equals("description")) // select 断言，只查询description之外的字段
                .eq(BeanUtils.isNotEmpty(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(BeanUtils.isNotEmpty(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(BooleanUtils.isTrue(query.getOnlyMine()), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());

        List<InteractionQuestion> records = description.getRecords();
        if (ObjectUtil.isEmpty(records)){
            throw new BadRequestException("adsd");
        }




        // 3、补充信息查询：查询提问者信息（非匿名）、查询最近一次回答信息
        // 3.1、收集提问者ID集合、最近一次回答主键ID集合
        HashSet<Long> userid= new HashSet<>();
        HashSet<Long> latestAnswerId= new HashSet<>();
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()){
                userid.add(record.getUserId());
            }
            latestAnswerId.add(record.getLatestAnswerId());
        }


        // 3.2、根据最近一次回答主键ID集合查询 最近一次回答信息 -> 转成Map（最近一次回答ID：最近一次回答信息对象）
        List<InteractionReply> interactionReplies = replyService.listByIds(latestAnswerId);
        Map<Long,InteractionReply> interactionReplyMap =new HashMap<>(interactionReplies.size());
        if (ObjectUtil.isNotEmpty(interactionReplyMap)){
            for (InteractionReply interactionReply : interactionReplies) {
                if (!interactionReply.getAnonymity()){
                    userid.add(interactionReply.getUserId());
                }
                interactionReplyMap.put(interactionReply.getId(),interactionReply);
            }
        }



        // 3.3、根据用户ID集合远程调用用户微服务，查询用户信息 -> 转成Map（用户ID：用户信息对象）
        List<UserDTO> userDTOS = userClient.queryUserByIds(userid);
        Map<Long, UserDTO> collect1 = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));


        // 4、循环遍历分页数据，封装VO集合
        List<QuestionVO> voPageDto =new ArrayList<>();
        for (InteractionQuestion record : records) {
            // 4.1、将po转为vo
            QuestionVO questionVO = BeanUtils.copyBean(record, QuestionVO.class);
            // 4.2、补充提问者的信息（提问者昵称、头像）
            UserDTO userDTO = collect1.get(record.getUserId());
            questionVO.setUserName(userDTO.getUsername());
            questionVO.setUserIcon(userDTO.getIcon());

            // 4.3、补充最近一次回答者的信息（最近一次回答者的昵称、最近一次回答内容）
            InteractionReply interactionReply = interactionReplyMap.get(record.getLatestAnswerId());
            if (ObjectUtil.isNotEmpty(interactionReply)){
                questionVO.setLatestReplyContent(interactionReply.getContent());
                if (!record.getAnonymity()){
                    UserDTO userDTO1 = collect1.get(record.getUserId());
                    if (ObjectUtil.isNotEmpty(userDTO1)){
                        questionVO.setLatestReplyUser(userDTO1.getName());
                    }
                }
            }

            // 4.4、添加至List
            voPageDto.add(questionVO);
        }

        // 5、封装PageDTO并返回
        return PageDTO.of(description,voPageDto);

    }

    /**
     * 用户端查看问题详情
     * @param id
     * @return
     */
    @Override
    public QuestionVO queryById(Long id) {

        InteractionQuestion interactionQuestion = this.lambdaQuery().eq(InteractionQuestion::getId, id).one();
        if (interactionQuestion.getHidden()||ObjectUtil.isEmpty(interactionQuestion)){
            return  null;
        }

        UserDTO userDTO = null;
        if (!interactionQuestion.getAnonymity()){
            userClient.queryUserById(interactionQuestion.getUserId());
        }
        QuestionVO questionVO = BeanUtils.copyBean(interactionQuestion, QuestionVO.class);
        if (ObjectUtil.isNotEmpty(questionVO)) {
            questionVO.setUserName(userDTO.getName());
            questionVO.setUserIcon(userDTO.getIcon());
        }

        return questionVO;


    }

    /**
     * 管理端分页查询互动问题
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery query) {

        List<Long> courseIds = null;
        //根据课程名从es中获取对应的课程id
        if (ObjectUtil.isNotEmpty(query.getCourseName())){
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (ObjectUtil.isEmpty(courseIds)){
                return PageDTO.empty(0L,0L);
            }
        }

        // 2、分页查询问题列表
        // select * from interaction_question where course_id in (1,2,3)
        // and status = ? and create_time >= ? and create_time <= ? order by create_time desc limit ?,?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .in(ObjectUtils.isNotEmpty(courseIds),InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtils.isNotEmpty(query.getStatus()),InteractionQuestion::getStatus, query.getStatus())
                .ge(ObjectUtils.isNotEmpty(query.getBeginTime()),InteractionQuestion::getCreateTime, query.getBeginTime())
                .le(ObjectUtils.isNotEmpty(query.getEndTime()),InteractionQuestion::getCreateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3、补充信息查询（章节信息、课程数据、用户数据）
        // 3.0、收集各种业务ID
        HashSet<Long> userIds = new HashSet<>(records.size()); // 用户ID集合
        HashSet<Long> cIds = new HashSet<>(records.size());// 课程ID集合
        HashSet<Long> cataIds = new HashSet<>(records.size());  // 章节ID集合
        for (InteractionQuestion record : records) {
            userIds.add(record.getUserId());
            cIds.add(record.getCourseId());
            cataIds.add(record.getChapterId());
            cataIds.add(record.getSectionId());
        }

        // 3.1、根据用户ID集合查询用户数据
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, String> userDTOMap= new HashMap<>(userIds.size());
        if (ObjectUtil.isNotEmpty(userDTOS)){
            userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId,UserDTO::getName));
        }


        // 3.2、根据课程ID集合查询课程数据
        Map<Long, CourseSimpleInfoDTO> couseInfoMap = new HashMap<>(cIds.size());
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(cIds);
        if (ObjectUtil.isNotEmpty(simpleInfoList)) {
            couseInfoMap = simpleInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }


        // 3.3、根据章节ID集合查询章节数据
        Map<Long, String> cataInfoList =new HashMap<>(cataIds.size());
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(cataIds);
        if (ObjectUtil.isNotEmpty(cataSimpleInfoDTOS)){
             cataInfoList = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }


        // 3.4、查出所有的分类（分类ID：分类名字）
//        Map<Long, String> allCategoryMap =new HashMap<>();
//        List<CategoryBasicDTO> allOfOneLevel = categoryClient.getAllOfOneLevel();
//        if (ObjectUtil.isNotEmpty(allOfOneLevel)){
//         allCategoryMap = allOfOneLevel.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, CategoryBasicDTO::getName));
//        }


        // 4、循环分页数据列表，填充各种数据
        List<QuestionAdminVO> voList =new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            // 4.1、属性拷贝，po -> vo
            QuestionAdminVO questionAdminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);
            // 4.2、填充用户昵称
            questionAdminVO.setUserName(userDTOMap.getOrDefault(record.getUserId(),""));
            // 4.3、填充课程名称 和 三级分类信息
            CourseSimpleInfoDTO courseSimpleInfoDTO = couseInfoMap.get(record.getCourseId());
            if (ObjectUtil.isNotEmpty(courseSimpleInfoDTO)){
                questionAdminVO.setCourseName(courseSimpleInfoDTO.getName());
//
//                String catagoryNames = allCategoryMap.get(courseSimpleInfoDTO.getFirstCateId())+
//                        "/"+allCategoryMap.get(courseSimpleInfoDTO.getSecondCateId())+
//                        "/"+allCategoryMap.get(courseSimpleInfoDTO.getThirdCateId());
                questionAdminVO.setCategoryName(categoryCache.getCategoryNames(courseSimpleInfoDTO.getCategoryIds()));
            }
            // 4.4、填充章节信息
            questionAdminVO.setChapterName(cataInfoList.getOrDefault(record.getChapterId(),""));
            questionAdminVO.setSectionName(cataInfoList.getOrDefault(record.getSectionId(),""));
            // 4.5、添加vo至list
            voList.add(questionAdminVO);
        }

        // 5、封装PageDTO并返回
        return PageDTO.of(pageResult,voList);
    }


    /**
     * 5、根据ID删除互动问题（Day5 - 实战）
     *
     * @param id
     */
    @Override
    public void deleteById(Long id) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion byId = getById(id);
        if (byId == null) {
            return;
        }
        // 3.判断是否是当前用户的问题
        if (!byId.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权删除他人的问题");
        }
        // 4.删除问题
        removeById(id);
        // 5.删除回答
        replyService.remove(
                new QueryWrapper<InteractionReply>().lambda().eq(InteractionReply::getQuestionId, id)
        );
    }


    /**
     * 6、根据ID修改互动问题（Day5 - 实战）
     *
     * @param id
     * @param questionDTO
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {

        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion q = getById(id);
        if (q == null) {
            throw new BadRequestException("问题不存在");
        }
        // 3.判断是否是当前用户的问题
        if (!q.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权修改他人的问题");
        }
        // 4.修改问题
        InteractionQuestion question = BeanUtils.toBean(questionDTO,InteractionQuestion.class);
        question.setId(id);
        updateById(question);
    }


    /**
     * 7、管理端根据ID查询互动问题（Day5 - 实战）
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO queryQuestionByIdAdmin(Long id) {
        // 1.根据id查询问题
        InteractionQuestion question = getById(id);
        if (question == null) {
            return null;
        }
        // 2.转PO为VO
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        // 3.查询提问者信息
        UserDTO user = userClient.queryUserById(question.getUserId());
        if (user != null) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        // 4.查询课程信息
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(
                question.getCourseId(), false, true);
        if (cInfo != null) {
            // 4.1.课程名称信息
            vo.setCourseName(cInfo.getName());
            // 4.2.分类信息
            vo.setCategoryName(categoryCache.getCategoryNames(cInfo.getCategoryIds()));
            // 4.3.教师信息
            List<Long> teacherIds = cInfo.getTeacherIds();
            List<UserDTO> teachers = userClient.queryUserByIds(teacherIds);
            if (ObjectUtil.isNotEmpty(teachers)) {
                vo.setTeacherName(teachers.stream()
                        .map(UserDTO::getName).collect(Collectors.joining("/")));
            }
        }
        // 5.查询章节信息
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(
                List.of(question.getChapterId(), question.getSectionId()));
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (ObjectUtil.isNotEmpty(catas)) {
            cataMap = catas.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setChapterName(cataMap.getOrDefault(question.getChapterId(), ""));
        vo.setSectionName(cataMap.getOrDefault(question.getSectionId(), ""));
        // 6.封装VO
        return vo;
    }

    @Override
    public void hiddenQuestion(Long id, Boolean hidden) {
        // 1.更新问题
        InteractionQuestion question =new InteractionQuestion();
        question.setId(id);
        question.setHidden(hidden);
        updateById(question);

        // 2.隐藏该问题下的所有回答和评论
        replyService.update(null,
                Wrappers.<InteractionReply>lambdaUpdate()
                        .set(InteractionReply::getHidden, hidden)
                        .eq(InteractionReply::getQuestionId, id)
        );
    }


}



















